package com.woniuxy.goods.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.core.util.ObjectCoverUtil;
import com.woniuxy.core.util.StateNum;
import com.woniuxy.goods.client.AdminFeignClient;
import com.woniuxy.goods.dto.*;
import com.woniuxy.goods.entity.*;
import com.woniuxy.goods.mapper.GoodsMapper;
import com.woniuxy.goods.param.*;
import com.woniuxy.goods.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.openfeign.util.Result;
import com.woniuxy.oss.util.FileUtil;
import com.woniuxy.oss.util.OSSUtil;
import com.woniuxy.redis.util.RedisKey;
import com.woniuxy.redis.util.RedisUtil;
import io.seata.spring.annotation.GlobalTransactional;
import org.aspectj.weaver.ast.Var;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 * 典当物品管理服务层实现类
 * @author ...
 * @since 2024年05月22日
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {

    /**
     * 品牌管理服务层接口
     */
    @Resource
    private BrandService brandService;

    /**
     * 类别管理服务层接口
     */
    @Resource
    private GoodsCatService catService;

    /**
     * 属性组管理服务层接口
     */
    @Resource
    private AttributeGroupService groupService;

    /**
     * 属性组属性配置服务层接口
     */
    @Resource
    private AttributeConfigService configService;

    /**
     * 调用admin模块接口
     */
    @Resource
    private AdminFeignClient adminFeignClient;

    /**
     * 定义图管理服务层接口
     */
    @Resource
    private GoodsCatPictureService catPictureService;

    /**
     * 文件上传OSS工具类
     */
    @Resource
    private OSSUtil ossUtil;

    /**
     * 典当物品日志管理服务层接口
     */
    @Resource
    private UpgoodsLogService upgoodsLogService;
    /**
     * 流程执行服务层接口
     */
    @Resource
    private ProcessExecuteService executeService;
    /**
     * 流程模型服务层接口
     */
    @Resource
    private ProcessModelService modelService;
    /**
     * 属性组类别绑定服务层接口
     */
    @Resource
    private GroupTypeService groupTypeService;
    /**
     * redis工具类
     */
    @Resource
    private RedisUtil redisUtil;
    /**
     * 消息队列工具类
     */
    @Resource
    private RabbitTemplate rabbitTemplate;


    /**
     * 新增典当物品(暂存)
     * @param param 新增典当物品对象
     * @return 典当物品对象
     * @throws Exception
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public GoodsDto addGoods(AddGoodsParam param) throws Exception {
        //通过系统模块查找当前登录管理员
//        计入录入人信息
        Result result = adminFeignClient.findAdminInfoByAccountId(param.getAccountId());
        if (result.getCode()!=200) throw new Exception(result.getMessage());
        AccountDto account = ObjectCoverUtil.castT(result.getData(), AccountDto.class);
        if (account==null||account.getState()!=StateNum.ACCOUNT_STATE_NORMAL) throw new Exception("管理员账号异常");
        //检查门店
        Result result2 = adminFeignClient.findShopByAccountId(param.getAccountId());
        if (result2.getCode()!=200) throw new Exception(result2.getMessage());
        ShopDto shop = ObjectCoverUtil.castT(result2.getData(), ShopDto.class);
        if (shop==null||shop.getState()!=StateNum.SHOP_STATE_NORMAL) throw new Exception("门店异常");
        //查品牌
        Brand brand = brandService.findBrandById(param.getBrandId());
        if (brand==null||brand.getIsShow()!= StateNum.BRAND_STATE_NORMAL) throw new Exception("所选品牌不可用");
        //查属性组
        GroupTypeDto groupType = groupTypeService.findGroupTypeByCatGroup(param.getSubCatId(),param.getGroupId());
        if (groupType==null) throw new Exception("属性组类别绑定异常");
        AttrGroupDto group = groupService.findAttrGroupById(param.getGroupId());
        if (group==null||group.getGroupState()!=StateNum.ATTR_GROUP_STATE_NORMAL) throw new Exception("所选属性组不可用");
        //查类别
        GoodsCat subCat = catService.findCatById(param.getSubCatId());
        if (subCat==null||subCat.getUpCatId()==0||subCat.getIsShow()!=StateNum.CAT_STATE_NORMAL) throw new Exception("二级类别异常");
        if (subCat.getCatId()!=groupType.getCatId()) throw new Exception("二级类别异常");
        GoodsCat cat = catService.findCatById(subCat.getUpCatId());
        if (cat==null||cat.getUpCatId()!=0||cat.getIsShow()!=StateNum.CAT_STATE_NORMAL) throw new Exception("一级类别异常");
        //查出对应属性列表
        Map<String,String> attrValue = new HashMap<>();
        Map<String, Object> attrMap = param.getGoodsAttribute();
        List<AttrConfigDto> config = configService.findConfigByGroupId(group.getGroupId());
        for (AttrConfigDto dto : config) {
            AttrInfoDto info = dto.getInfoDto();
            Object value = attrMap.get(info.getAttributeId().toString());
            if (ObjectUtil.isEmpty(value)) throw new Exception(info.getAttributeName()+"属性值不能为空");
            if (info.getAttributeType()==StateNum.ATTR_INFO_TYPE_ONLY){
                //自定义值
                attrValue.put(info.getAttributeName(),value.toString());
            } else if (info.getAttributeType()==StateNum.ATTR_INFO_TYPE_SINGLE_CHOICE) {
                //单选值，不能有多个
                if (value instanceof List) throw new Exception(info.getAttributeName()+"属性值为单选");
                if (!info.getChoices().contains(value)) throw new Exception(info.getAttributeName()+"不存在值："+value);
                attrValue.put(info.getAttributeName(),value.toString());
            } else if (info.getAttributeType()==StateNum.ATTR_INFO_TYPE_MULTIPLE_CHOICE) {
                //多选值
                List<Object> choice = (List<Object>) value;
                if (!info.getChoices().containsAll(choice)) throw new Exception(info.getAttributeName()+"不存在所选值");
                attrValue.put(info.getAttributeName(),choice.toString());
            }
        }
        //完善goods信息
        Goods goods = BeanUtil.toBean(param, Goods.class);
        String goodsAttribute = JSONUtil.toJsonStr(param.getGoodsAttribute());
        goods.setCatId(cat.getCatId());
        goods.setSubCatId(subCat.getCatId());
        goods.setShopId(shop.getShopId());
        goods.setGoodsAttribute(goodsAttribute);
        goods.setGoodsNum(1);
        goods.setInputUser(account.getAdminName());
        goods.setShopName(shop.getShopName());
        goods.setGroupId(group.getGroupId());
        goods.setGoodsPicture(null);
        String json = JSONUtil.toJsonStr(goods);
        //存入redis
        redisUtil.set(RedisKey.cacheGoods(shop.getShopId()),json);
        //返回值
        GoodsDto goodsDto = BeanUtil.toBean(goods, GoodsDto.class);
        goodsDto.setAttrMap(param.getGoodsAttribute());
        goodsDto.setBrandName(brand.getBrandName());
        String route = cat.getCatName()+">"+subCat.getCatName()+">"+group.getGroupName();
        goodsDto.setRoute(route);
        return goodsDto;
    }

    /**
     * 上传鉴定图
     * @param param 新增物品鉴定图参数对象
     * @param picture 定义图文件
     * @return 鉴定图地址
     * @throws Exception
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public String addGoodsPicture(AddGoodsPictureParam param, MultipartFile picture) throws Exception {
        //通过系统模块查找当前登录管理员
        Result result = adminFeignClient.findAdminInfoByAccountId(param.getAccountId());
        if (result.getCode()!=200) throw new Exception(result.getMessage());
        AccountDto account = ObjectCoverUtil.castT(result.getData(), AccountDto.class);
        if (account==null||account.getState()!=StateNum.ACCOUNT_STATE_NORMAL) throw new Exception("管理员账号异常");
        //检查门店
        Result result2 = adminFeignClient.findShopByAccountId(param.getAccountId());
        if (result2.getCode()!=200) throw new Exception(result2.getMessage());
        ShopDto shop = ObjectCoverUtil.castT(result2.getData(), ShopDto.class);
        if (shop==null||shop.getState()!=StateNum.SHOP_STATE_NORMAL) throw new Exception("门店异常");
        //取出缓存goods
        String json = redisUtil.get(RedisKey.cacheGoods(shop.getShopId()));
        Goods goods = JSONObject.parseObject(json, Goods.class);
        //获取物品鉴定图
        Map<String,String> map = new HashMap<>();
        String goodsPicture = goods.getGoodsPicture();
        if (ObjectUtil.isNotEmpty(goodsPicture)){
            map = JSONObject.parseObject(goodsPicture, Map.class);
        }
        //判断定义图
        CatPictureListDto pictures = catPictureService.findCatPictureByCatId(goods.getSubCatId());
        List<GoodsCatPictureDto> mustChoice = pictures.getMustChoice();//必选图片集合
        List<GoodsCatPictureDto> couldChoice = pictures.getCouldChoice();//可选图片集合
        Set<Integer> list = mustChoice.stream().map(o -> o.getId()).collect(Collectors.toSet());
        Set<Integer> list2 = couldChoice.stream().map(o -> o.getId()).collect(Collectors.toSet());
        list.addAll(list2);
        if (!list.contains(param.getId())) throw new Exception("上传鉴定图类型异常");
        if(!FileUtil.isImageFile(picture.getInputStream())){
            throw new Exception("上传失败，上传文件非图片格式");
        }
        GoodsCatPicture catPicture = catPictureService.findCatPictureById(param.getId());
        String name = picture.getOriginalFilename();
        String sufix = name.substring(name.lastIndexOf("."));
        String newName = UUID.randomUUID().toString();
        String pictureRouter = ossUtil.uploadFile(picture.getInputStream(), newName + sufix, "class108-pawn");
        if (ObjectUtil.isNotEmpty(map.get(catPicture.getPictureName()))){
            String url = map.get(catPicture.getPictureName());
            String imgName = url.replace("https://class108-pawn.oss-cn-chengdu.aliyuncs.com/","");
            ossUtil.deleteFile("class108-pawn",imgName);
        }
        map.put(catPicture.getPictureName(),pictureRouter);
        //修改goods
        goods.setGoodsPicture(JSONUtil.toJsonStr(map));
        String json1 = JSONUtil.toJsonStr(goods);
        redisUtil.set(RedisKey.cacheGoods(shop.getShopId()),json1);
        return pictureRouter;
    }

    /**
     * 保存物品
     * @param accountId 账号id
     * @return 物品dto对象
     * @throws Exception
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public GoodsDto saveGoods(Integer accountId) throws Exception {
        //通过系统模块查找当前登录管理员
        Result result = adminFeignClient.findAdminInfoByAccountId(accountId);
        if (result.getCode()!=200) throw new Exception(result.getMessage());
        AccountDto account = ObjectCoverUtil.castT(result.getData(), AccountDto.class);
        if (account==null||account.getState()!=StateNum.ACCOUNT_STATE_NORMAL) throw new Exception("管理员账号异常");
        //检查门店
        Result result2 = adminFeignClient.findShopByAccountId(accountId);
        if (result2.getCode()!=200) throw new Exception(result2.getMessage());
        ShopDto shop = ObjectCoverUtil.castT(result2.getData(), ShopDto.class);
        if (shop==null||shop.getState()!=StateNum.SHOP_STATE_NORMAL) throw new Exception("门店异常");
        //获取redis
        String json = redisUtil.get(RedisKey.cacheGoods(shop.getShopId()));
        Goods goods = JSONObject.parseObject(json, Goods.class);
        if (goods==null) throw new Exception("信息未完善");
        //查品牌
        Brand brand = brandService.findBrandById(goods.getBrandId());
        if (brand==null||brand.getIsShow()!= StateNum.BRAND_STATE_NORMAL) throw new Exception("所选品牌不可用");
        //查属性组
        GroupTypeDto groupType = groupTypeService.findGroupTypeByCatGroup(goods.getSubCatId(),goods.getGroupId());
        if (groupType==null) throw new Exception("属性组类别绑定异常");
        AttrGroupDto group = groupService.findAttrGroupById(groupType.getGroupDto().getGroupId());
        if (group==null||group.getGroupState()!=StateNum.ATTR_GROUP_STATE_NORMAL) throw new Exception("所选属性组不可用");
        //查类别
        GoodsCat subCat = catService.findCatById(groupType.getCatId());
        if (subCat==null||subCat.getUpCatId()==0||subCat.getIsShow()!=StateNum.CAT_STATE_NORMAL) throw new Exception("二级类别异常");
        GoodsCat cat = catService.findCatById(subCat.getUpCatId());
        if (cat==null||cat.getUpCatId()!=0||cat.getIsShow()!=StateNum.CAT_STATE_NORMAL) throw new Exception("一级类别异常");
        //判断定义图
        CatPictureListDto pictures = catPictureService.findCatPictureByCatId(goods.getSubCatId());
        List<GoodsCatPictureDto> mustChoice = pictures.getMustChoice();//必选集合
        Map map = JSONObject.parseObject(goods.getGoodsPicture(), Map.class);
        for (GoodsCatPictureDto picture : mustChoice) {
            if (ObjectUtil.isEmpty(map.get(picture.getPictureName()))){
                throw new Exception("有必选鉴定图未上传");
            }
        }
        //完善goods
        goods.setInputTime(LocalDateTime.now().toString());
        goods.setGoodsState(StateNum.GOODS_IS_NOT_STORE);
        goods.setProcessExecuteId(StateNum.GOODS_PROCESS_NOT_APPR);
        goods.setIsSalable(StateNum.GOODS_IS_NOT_SALABLE);
        goods.setIsInProc(StateNum.GOODS_IN_PROCESS);
        save(goods);
        //消息队列创建流程执行和日志
        rabbitTemplate.convertAndSend("sava_goods_queue",goods);

        //返回值
        GoodsDto goodsDto = BeanUtil.toBean(goods, GoodsDto.class);
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> attrValue = mapper.readValue(goods.getGoodsAttribute(), Map.class);
        goodsDto.setAttrMap(attrValue);
        goodsDto.setProcessExecuteName(modelService.findStateNameByNum(goods.getProcessExecuteId(),1));
        goodsDto.setBrandName(brand.getBrandName());
        String route = cat.getCatName()+">"+subCat.getCatName()+">"+group.getGroupName();
        goodsDto.setRoute(route);
        return goodsDto;
    }

    /**
     * 修改典当物品状态
     * @param goodsId 典当物品对象id
     * @param stateNUm 状态码
     * @return 典当物品对象
     * @throws Exception
     */
    @Override
    public GoodsDto updateGoodsStateNum(Integer goodsId, Integer stateNUm) throws Exception {
        Goods goods = getById(goodsId);
        if (goods==null) throw new Exception("物品不存在");
        goods.setProcessExecuteId(stateNUm);
        updateById(goods);
        return findGoodsById(goodsId);
    }

    @Override
    @GlobalTransactional(rollbackFor =  Throwable.class)
    public GoodsDto updateGoodsByEntity(Goods goods) throws Exception {
        updateById(goods);
        return findGoodsById(goods.getGoodsId());
    }

    /**
     * 修改典当物品流程
     * @param goodsId 典当物品对象id
     * @param stateNUm 状态码
     * @param accountId 当前登录账号id
     * @return 典当物品对象
     * @throws Exception
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public GoodsDto updateGoodsProcess(Integer goodsId, Integer stateNUm,Integer accountId) throws Exception {
        Goods goods = getById(goodsId);
        if (goods==null) throw new Exception("物品不存在");
        ProcessExecute execute = executeService.findExecuteByStateNumGoodsId(goods.getProcessExecuteId(), goodsId);
        if (execute.getIsActive()!=StateNum.GOODS_IS_ACTIVE||goods.getProcessExecuteId()!=StateNum.GOODS_PROCESS_NOT_STORE) throw new Exception("状态不处于待审核");
        if (execute.getAccountId()!=accountId) throw new Exception("无权限审核该物品");
        if (stateNUm!=4&&stateNUm!=1&&stateNUm!=2) throw new Exception("流程码异常");
        goods.setProcessExecuteId(stateNUm);
        updateById(goods);
        executeService.updateProcessByGoodsId(goodsId,stateNUm);
        return findGoodsById(goodsId);
    }

    /**
     * 修改典当物品
     * @param param 修改典当物品对象
     * @return 典当物品对象
     * @throws Exception
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public GoodsDto updateGoods(UpdateGoodsParam param) throws Exception {
        //查物品
        GoodsDto goodsDto = this.findGoodsById(param.getGoodsId());
        if (goodsDto==null) throw new Exception("物品不存在");
        Goods goods = BeanUtil.toBean(param, Goods.class);
        //通过系统模块查找当前登录管理员
        Result result = adminFeignClient.findAdminInfoByAccountId(param.getAccountId());
        if (result.getCode()!=200) throw new Exception(result.getMessage());
        AccountDto account = ObjectCoverUtil.castT(result.getData(), AccountDto.class);
        if (account==null||account.getState()!=StateNum.ACCOUNT_STATE_NORMAL) throw new Exception("管理员账号异常");
        //查属性组
        GroupTypeDto groupType = groupTypeService.findGroupTypeByCatGroup(param.getSubCatId(),param.getGroupId());
        if (groupType==null) throw new Exception("属性组类别绑定异常");
        AttrGroupDto group = groupService.findAttrGroupById(param.getGroupId());
        if (group==null||group.getGroupState()!=StateNum.ATTR_GROUP_STATE_NORMAL) throw new Exception("所选属性组不可用");
        //查类别
        GoodsCat subCat = catService.findCatById(param.getSubCatId());
        if (subCat==null||subCat.getUpCatId()==0||subCat.getIsShow()!=StateNum.CAT_STATE_NORMAL) throw new Exception("二级类别异常");
        if (subCat.getCatId()!=groupType.getCatId()) throw new Exception("二级类别异常");
        //查看图片
        String pictureStr = redisUtil.get(RedisKey.modifyGoodsPicture(goods.getGoodsId()));//redis新上传
        System.out.println("====redis取出=======================================================");
        System.out.println(pictureStr);
        ObjectMapper mapper = new ObjectMapper();
        Map<String, String> map = new HashMap<>();
        Map<String, String> picture = goodsDto.getPicture();//数据库
        Set<String> mapKey = new HashSet<>();
        System.out.println("====数据库取出=====================================================");
        System.out.println(picture);
        //判断是否上传全部必须
        CatPictureListDto pictures = catPictureService.findCatPictureByCatId(subCat.getCatId());
        List<GoodsCatPictureDto> mustChoice = pictures.getMustChoice();//必选集合
        List<GoodsCatPictureDto> couldChoice = pictures.getCouldChoice();//可选集合
        Set<String> mustString = mustChoice.stream().map(o -> o.getPictureName()).collect(Collectors.toSet());
        Set<String> couldString = couldChoice.stream().map(o -> o.getPictureName()).collect(Collectors.toSet());
        Set<String> allString = new HashSet<>(mustString);
        allString.addAll(couldString);
        System.out.println("==============================================================");
        System.out.println(mustString);
        System.out.println("==============================================================");
        if(ObjectUtil.isNotEmpty(pictureStr)){
            map = mapper.readValue(pictureStr, Map.class);
            mapKey = map.entrySet().stream().map(o -> o.getKey()).collect(Collectors.toSet());
            System.out.println("===redis里面取出的key===================================================");
            System.out.println(mapKey);
            System.out.println("==============================================================");
            //删除数据库中重复的的鉴定图文件
            Set<String> skey = picture.entrySet().stream().map(o -> o.getKey()).collect(Collectors.toSet());
            System.out.println("===数据库里面取出的key===================================================");
            System.out.println(skey);
            System.out.println("==============================================================");
            for (String s : skey) {
                if (mapKey.contains(s)){
//                    String url = picture.get(s);
//                    String imgName = url.replace("https://class108-pawn.oss-cn-chengdu.aliyuncs.com/","");
//                    ossUtil.deleteFile("class108-pawn",imgName);
                    System.out.println("====redis key 和 数据库key相同=================================");
                    picture.remove(s);
                }

            }
            //判断是否上传全部必须
            Set<String> set =  new HashSet<>(allString);
            for (String s : mapKey) {
                if (!set.contains(s)){
                    map.remove(s);
                }
            }
            System.out.println("==============================================================");
            System.out.println(map);
            System.out.println("==============================================================");
        }
        map.putAll(picture);
        if (ObjectUtils.isEmpty(mapKey)) mapKey = map.entrySet().stream().map(o -> o.getKey()).collect(Collectors.toSet());
        Set<String> collect = picture.entrySet().stream().map(o -> o.getKey()).collect(Collectors.toSet());
        mapKey.addAll(collect);
        System.out.println("==============================================================");
        System.out.println(mapKey);
        System.out.println("==============================================================");
        //删除最新多余图片
        Set<String> set =  new HashSet<>(allString);
        for (String s : mapKey) {
            if (!set.contains(s)){
                map.remove(s);
            }
        }
        if (ObjectUtils.isEmpty(mapKey)) mapKey = map.entrySet().stream().map(o -> o.getKey()).collect(Collectors.toSet());
        System.out.println("==============================================================");
        System.out.println(mustString);
        System.out.println(mapKey);
        System.out.println("==============================================================");
        if (!mapKey.containsAll(mustString)){
            throw new Exception("有必选鉴定图未上传");
        }
        redisUtil.set(RedisKey.modifyGoodsPicture(goods.getGoodsId()),JSONUtil.toJsonStr(map));

        GoodsCat cat = catService.findCatById(subCat.getUpCatId());
        if (cat==null||cat.getUpCatId()!=0||cat.getIsShow()!=StateNum.CAT_STATE_NORMAL) throw new Exception("一级类别异常");
        //查出对应属性列表
        Map<String,String> attrValue = new HashMap<>();
        Map<String, Object> attrMap = param.getGoodsAttribute();
        System.out.println(attrMap);
        List<AttrConfigDto> config = configService.findConfigByGroupId(group.getGroupId());
        for (AttrConfigDto dto : config) {
            AttrInfoDto info = dto.getInfoDto();
            System.out.println(info);
            System.out.println("=========================================================");
            Object value = attrMap.get(info.getAttributeId().toString());
            if (ObjectUtil.isEmpty(value)) throw new Exception(info.getAttributeName()+"属性值不能为空");
            if (info.getAttributeType()==StateNum.ATTR_INFO_TYPE_ONLY){
                //自定义值
                attrValue.put(info.getAttributeName(),value.toString());
            } else if (info.getAttributeType()==StateNum.ATTR_INFO_TYPE_SINGLE_CHOICE) {
                //单选值，不能有多个
                if (value instanceof List) throw new Exception(info.getAttributeName()+"属性值为单选");
                if (!info.getChoices().contains(value)) throw new Exception(info.getAttributeName()+"不存在值："+value);
                attrValue.put(info.getAttributeName(),value.toString());
            } else if (info.getAttributeType()==StateNum.ATTR_INFO_TYPE_MULTIPLE_CHOICE) {
                //多选值
                List<Object> choice = (List<Object>) value;
                if (!info.getChoices().containsAll(choice)) throw new Exception(info.getAttributeName()+"不存在所选值");
                attrValue.put(info.getAttributeName(),choice.toString());
            }
        }
        //完善goods信息
        String goodsAttribute = JSONUtil.toJsonStr(param.getGoodsAttribute());
        goods.setCatId(cat.getCatId());
        goods.setSubCatId(subCat.getCatId());
        goods.setGoodsAttribute(goodsAttribute);
        goods.setModifyBy(account.getAdminName());
        goods.setModifyTime(LocalDateTime.now().toString());
        goods.setGroupId(group.getGroupId());
        String s = redisUtil.get(RedisKey.modifyGoodsPicture(goods.getGoodsId()));
        if (ObjectUtil.isNotEmpty(s)){
            goods.setGoodsPicture(s);
        }
        updateById(goods);
        //返回值
        GoodsDto dto = findGoodsById(param.getGoodsId());
        //修改流程
        if (dto.getProcessExecuteId()==StateNum.GOODS_PROCESS_NOT_OVERALL){
            ProcessExecute execute = executeService.findExecuteByStateNumGoodsId(StateNum.GOODS_PROCESS_NOT_OVERALL, goods.getGoodsId());
            executeService.updateUpActiveById(execute.getProcessExecuteId());
        }
        String route = cat.getCatName()+">"+subCat.getCatName()+">"+group.getGroupName();
        //新增日志
        List<AddUpGoodsLogParam> change = new ArrayList<>();
        if (!route.equals(goodsDto.getRoute())){
            AddUpGoodsLogParam logParam = new AddUpGoodsLogParam();
            logParam.setGoodsId(goods.getGoodsId());
            logParam.setModifyBy(account.getAdminName());
            logParam.setUpdateDetails("将典当物品类别修改为"+route);
            change.add(logParam);
        }
        if (!goodsAttribute.equals(JSONUtil.toJsonStr(goodsDto.getAttrMap()))){
            AddUpGoodsLogParam logParam = new AddUpGoodsLogParam();
            logParam.setGoodsId(goods.getGoodsId());
            logParam.setModifyBy(account.getAdminName());
            logParam.setUpdateDetails("将典当物品属性修改为"+goodsAttribute);
            change.add(logParam);
        }
        if (!goods.getGoodsName().equals(goodsDto.getGoodsName())){
            AddUpGoodsLogParam logParam = new AddUpGoodsLogParam();
            logParam.setGoodsId(goods.getGoodsId());
            logParam.setModifyBy(account.getAdminName());
            logParam.setUpdateDetails("将典当物品名称修改为"+param.getGoodsName());
            change.add(logParam);
        }
        if (!goods.getGoodsDesc().equals(goodsDto.getGoodsDesc())){
            AddUpGoodsLogParam logParam = new AddUpGoodsLogParam();
            logParam.setGoodsId(goods.getGoodsId());
            logParam.setModifyBy(account.getAdminName());
            logParam.setUpdateDetails("将典当物品详情修改为"+goods.getGoodsDesc());
            change.add(logParam);
        }
        upgoodsLogService.addUpGoodsLogList(change);
        return goodsDto;
    }

    /**
     * 修改鉴定图
     * @param id 修改物品鉴定图id
     * @param goodsId 物品id
     * @param picture 定义图文件
     * @param accountId 当前登录管理员id
     * @return 鉴定图地址
     * @throws Exception
     */
    @Override
    public String modifyGoodsPicture(Integer accountId, Integer goodsId, Integer id, MultipartFile picture) throws Exception {
        Map<String,String> map = new HashMap<>();
        //通过系统模块查找当前登录管理员
        Result result = adminFeignClient.findAdminInfoByAccountId(accountId);
        if (result.getCode()!=200) throw new Exception(result.getMessage());
        AccountDto account = ObjectCoverUtil.castT(result.getData(), AccountDto.class);
        if (account==null||account.getState()!=StateNum.ACCOUNT_STATE_NORMAL) throw new Exception("管理员账号异常");
        //查物品
        GoodsDto goodsDto = this.findGoodsById(goodsId);
        if (goodsDto==null) throw new Exception("物品不存在");
        //判断定义图
        if(!FileUtil.isImageFile(picture.getInputStream())){
            throw new Exception("上传失败，上传文件非图片格式");
        }
        GoodsCatPicture catPicture = catPictureService.findCatPictureById(id);
        String name = picture.getOriginalFilename();
        String sufix = name.substring(name.lastIndexOf("."));
        String newName = UUID.randomUUID().toString();
        String pictureRouter = ossUtil.uploadFile(picture.getInputStream(), newName + sufix, "class108-pawn");
        //获取物品鉴定图
        if (redisUtil.get(RedisKey.modifyGoodsPicture(goodsId))==null){
            map.put(catPicture.getPictureName(),pictureRouter);
            redisUtil.set(RedisKey.modifyGoodsPicture(goodsId),JSON.toJSONString(map));
        }else{
            map = JSONObject.parseObject(redisUtil.get(RedisKey.modifyGoodsPicture(goodsId)),Map.class);
            if (ObjectUtil.isNotEmpty(map.get(catPicture.getPictureName()))){
                String url = map.get(catPicture.getPictureName());
                String imgName = url.replace("https://class108-pawn.oss-cn-chengdu.aliyuncs.com/","");
                ossUtil.deleteFile("class108-pawn",imgName);
            }
            map.put(catPicture.getPictureName(),pictureRouter);
        }
        //修改goods
        String s = JSONUtil.toJsonStr(map);
        System.out.println("----------------------------------------------");
        System.out.println("redis修改保存数据"+s);
        redisUtil.set(RedisKey.modifyGoodsPicture(goodsId),s);
        return pictureRouter;
    }

    /**
     * 根据id查找典当物品
     * @param goodsId 典当物品id
     * @return 典当物品对象
     * @throws Exception
     */
    @Override
    public Goods findById(Integer goodsId) throws Exception {
        return getById(goodsId);
    }

    /**
     * 根据id查找典当物品
     * @param goodsId 典当物品id
     * @return 典当物品对象
     * @throws Exception
     */
    @Override
    public GoodsDto findGoodsById(Integer goodsId) throws Exception {
        Goods goods = getById(goodsId);
        GoodsDto goodsDto = BeanUtil.toBean(goods, GoodsDto.class);
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> map = mapper.readValue(goods.getGoodsAttribute(), Map.class);
        goodsDto.setAttrMap(map);
        goodsDto.setPicture(JSON.parseObject(goods.getGoodsPicture(),Map.class));
        Brand brand = brandService.findBrandById(goods.getBrandId());
        goodsDto.setBrandName(brand.getBrandName());
        GoodsCat cat = catService.findCatById(goods.getCatId());
        GoodsCat subCat = catService.findCatById(goods.getSubCatId());
        AttrGroupDto group = groupService.findAttrGroupById(goods.getGroupId());
        String route = cat.getCatName()+">"+subCat.getCatName()+">"+group.getGroupName();
        goodsDto.setRoute(route);
        ProcessExecute execute = executeService.findExecuteByStateNumGoodsId(goods.getProcessExecuteId(), goods.getGoodsId());
        if (execute.getIsActive()!=StateNum.GOODS_IS_ACTIVE&&!execute.getStateName().equals(StateNum.APPRAISAL_FALSE)) throw new Exception("流程活跃异常");
        goodsDto.setExecute(BeanUtil.toBean(execute,ProcessExecuteDto.class));
        goodsDto.setProcessExecuteName(execute.getStateName());
        List<ProcessExecute> process = executeService.findProcessByGoodsId(goodsId);
        for (ProcessExecute processExecute : process) {
            if (processExecute.getStateNum()==StateNum.GOODS_PROCESS_NOT_APPR){
                Result result = adminFeignClient.findAdminInfoByAccountId(processExecute.getAccountId());
                if (result.getCode()!=200) throw new Exception(result.getMessage());
                String surveyor = ObjectCoverUtil.castT(result.getData(),AccountDto.class).getAdminName();
                goodsDto.setSurveyor(surveyor);
            } else if (processExecute.getStateNum()==StateNum.GOODS_PROCESS_NOT_EVAL) {
                Result result1 = adminFeignClient.findAdminInfoByAccountId(processExecute.getAccountId());
                if (result1.getCode()!=200) throw new Exception(result1.getMessage());
                String assessor = ObjectCoverUtil.castT(result1.getData(),AccountDto.class).getAdminName();
                goodsDto.setAssessor(assessor);
            }
        }
        return goodsDto;
    }

    /**
     * 根据ids查找物品
     * @param param 物品id集合
     * @return 典当物品对象分页对象
     * @throws Exception
     */
    @Override
    public IPage<GoodsDto> findGoodsByIds(FindGoodsPageParam param) throws Exception {
        Page<Goods> page = new Page<>(param.getPageNum(), param.getPageSize());
        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
        wrapper.in("goods_id",param.getGoodsIds());
        page(page,wrapper);
        IPage<GoodsDto> iPage = page.convert(v -> {
            GoodsDto dto = new GoodsDto();
            BeanUtil.copyProperties(v, dto);
            return dto;
        });
        List<GoodsDto> records = iPage.getRecords();
        for (GoodsDto record : records) {
            record = this.findGoodsById(record.getGoodsId());
        }
        iPage.setRecords(records);
        return iPage;
    }

    /**
     * 条件分页查找物品
     * @param param 典当物品分页查询对象
     * @return 典当物品对象分页对象
     * @throws Exception
     */
    @Override
    public IPage<GoodsDto> findGoodsPage(FindGoodsPageParam param) throws Exception {
        Page<Goods> page = new Page<>(param.getPageNum(), param.getPageSize());
        QueryWrapper<Goods> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("input_time");
        if (ObjectUtil.isNotEmpty(param.getGoodsName())){
            wrapper.like("goods_name",param.getGoodsName());
        }
        if (ObjectUtil.isNotEmpty(param.getBrandId())){
            wrapper.eq("brand_id",param.getBrandId());
        }
        if (ObjectUtil.isNotEmpty(param.getProcessExecuteId())){
            wrapper.eq("process_execute_id",param.getProcessExecuteId());
        }
        if (ObjectUtil.isNotEmpty(param.getCatId())){
            GoodsCat cat = catService.findCatById(param.getCatId());
            if (cat.getUpCatId()==0){
                wrapper.eq("cat_id",param.getCatId());
            }else{
                wrapper.eq("sub_cat_id",param.getCatId());
            }
        }
        if (ObjectUtil.isNotEmpty(param.getShopId())){
            wrapper.eq("shop_id",param.getShopId());
        }
        if (ObjectUtil.isNotEmpty(param.getInputUser())){
            wrapper.like("input_user",param.getInputUser());
        }
        if (ObjectUtil.isNotEmpty(param.getMinTime())){
            wrapper.gt("input_time",param.getMinTime());
        }
        if (ObjectUtil.isNotEmpty(param.getMaxTime())){
            wrapper.lt("input_time",param.getMaxTime());
        }
        if (ObjectUtil.isNotEmpty(param.getGoodsIds())){
            wrapper.in("goods_id",param.getGoodsIds());
        }
        page(page,wrapper);
        IPage<GoodsDto> iPage = page.convert(v -> {
            GoodsDto dto = new GoodsDto();
            BeanUtil.copyProperties(v, dto);
            return dto;
        });
        List<GoodsDto> records = iPage.getRecords();
        List<GoodsDto> dtoRecords = new ArrayList<>();
        for (GoodsDto record : records) {
            record = this.findGoodsById(record.getGoodsId());
            dtoRecords.add(record);
        }
        iPage.setRecords(dtoRecords);
        return iPage;
    }
}
